package edu.drexel.jrexel2d.rendering;

import java.util.ArrayList;

import org.lwjgl.opengl.GL11;
import org.newdawn.slick.Color;
import org.newdawn.slick.opengl.Texture;

import edu.drexel.jrexel2d.gamestate.Level;
import edu.drexel.jrexel2d.objects2D.*;

public class RenderingEngine {
	public void initGL() {
		GL11.glMatrixMode(GL11.GL_PROJECTION);
		GL11.glLoadIdentity();
		GL11.glEnable(GL11.GL_BLEND);
		GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
		GL11.glOrtho(0, 800, 600, 0, 1, -1);
		GL11.glMatrixMode(GL11.GL_MODELVIEW);
	}
 
	
	public void clear() {
		GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
	}
	
	public void renderObject(Object2D o) {
		Color.white.bind();
		Texture t = o.getTex() ;
		float tW = t.getTextureWidth() ;	// texture width/height
		float tH = t.getTextureHeight() ;
		float fW = o.getWidth() ;			// frame width/height
		float fH = o.getHeight() ;
		Point2D center = o.getLocation() ;
		int frame = o.getFrame() ;
		
		float x = center.getXF() - (o.getWidth()/2) ;
		float y = center.getYF() - (o.getHeight()/2) ;
		
		t.bind() ;
		GL11.glPushMatrix();
			GL11.glBegin(GL11.GL_QUADS);
				GL11.glTexCoord2f((frame*fW)/tW,0);
				GL11.glVertex2f(x,y);
				GL11.glTexCoord2f((fW/tW)+(frame*fW)/tW,0);
				GL11.glVertex2f(x+fW,y);
				GL11.glTexCoord2f((fW/tW)+(frame*fW)/tW,fH/tH);
				GL11.glVertex2f(x+fW,y+fH);
				GL11.glTexCoord2f((frame*fW)/tW,fH/tH);
				GL11.glVertex2f(x,y+fH);
			GL11.glEnd();
		GL11.glPopMatrix();
	}
	
	public void renderBackdrop(Backdrop b) {
		Color.white.bind();
		Texture t = b.getTex() ;
		float tW = t.getTextureWidth() ;	// texture width/height
		float tH = t.getTextureHeight() ;
		float fW = b.getWidth() ;			// frame width/height
		float fH = b.getHeight() ;
		Point2D location = b.getLocation() ;
		
		float x = location.getXF() ;
		float y = location.getYF() ;
		
		t.bind() ;
		GL11.glPushMatrix();
			GL11.glBegin(GL11.GL_QUADS);
				GL11.glTexCoord2f(0,0);
				GL11.glVertex2f(x,y);
				GL11.glTexCoord2f(fW/tW,0);
				GL11.glVertex2f(x+fW,y);
				GL11.glTexCoord2f(fW/tW,fH/tH);
				GL11.glVertex2f(x+fW,y+fH);
				GL11.glTexCoord2f(0,fH/tH);
				GL11.glVertex2f(x,y+fH);
			GL11.glEnd();
		GL11.glPopMatrix();
	}
	
	public void renderLevel(Level l, Boolean anim) {
		ArrayList<Object2D> objs = l.getObjects() ;
		ArrayList<Object2D> sorted = sort(objs) ;
		//System.out.println("Sorted List?:") ;
		for(int i=0; i<sorted.size(); i++) {
			//System.out.println(sorted.get(i).getBase().getY()) ;
		}

		renderBackdrop(l.getBackdrop()) ;
		for(int i=0; i<objs.size(); i++) {
			if(anim) {
				objs.get(i).animate() ;
			}
			renderObject(objs.get(i)) ;
		}
	}
	
	public ArrayList<Object2D> sort(ArrayList<Object2D> o) {
		ArrayList<Object2D> os = new ArrayList<Object2D>() ;
		os.addAll(o) ;
		quicksort(o, 0, o.size()-1) ;
		
		return os ;
	}
	
	private void quicksort(ArrayList<Object2D> o, int s, int e) {
		if(s >= e) return ;
		
		int pivot = pivot(o,s,e) ;
		quicksort(o,s,pivot-1) ;
		quicksort(o,pivot,e) ;
	}
	
	private int pivot(ArrayList<Object2D> o, int s, int e) {
		float pivot = o.get((s+e)/2).getBase().getYF() ;
		int i = s ;
		int j = e ;
		
		while (i <= j) {
			while(o.get(i).getBase().getYF() < pivot) {
				i++;
			}
			while(o.get(j).getBase().getYF() > pivot) {
				j--;
			}
			if(i <= j) {
				swap(o, i, j);
				i++ ;
				j-- ;
			}
		}
		return i;
	}
	
	private void swap(ArrayList<Object2D> o, int s, int e) {
		for(int i=0; i<o.size(); i++) {
			//System.out.println(o.get(i).getBase().getY()) ;
		}
		Object2D temp = o.get(s) ;
		o.set(s, o.get(e)) ;
		o.set(e, temp) ;
		for(int i=0; i<o.size(); i++) {
			//System.out.println(o.get(i).getBase().getY()) ;
		}
	}
}
